package hk.com.fgoproduction.getdroplets.Activity

import android.app.ProgressDialog
import android.content.Intent
import android.os.Bundle
import android.widget.ListView
import com.dropbox.core.v2.files.FileMetadata
import com.dropbox.core.v2.files.FolderMetadata
import com.dropbox.core.v2.files.ListFolderResult
import com.dropbox.core.v2.files.Metadata
import hk.com.fgoproduction.getdroplets.Activity.ReconnectActivity
import hk.com.fgoproduction.getdroplets.DropboxAPI.AFile
import hk.com.fgoproduction.getdroplets.Lib.Common.ThisApplication
import hk.com.fgoproduction.getdroplets.Lib.Common.ToolInstance.CheckConnection
import hk.com.fgoproduction.getdroplets.Lib.Common.ToolInstance.LogInstance
import hk.com.fgoproduction.getdroplets.Lib.FileMan.FileManActFrame
import hk.com.fgoproduction.getdroplets.Lib.TreeList.TreeList
import hk.com.fgoproduction.getdroplets.R
import kotlinx.android.synthetic.main.file_man_view.*
import org.jetbrains.anko.onClick
import org.jetbrains.anko.toast

class DropboxManAct : FileManActFrame(), ThisApplication.BgThreadCallback {

    override val showLog = true
    override val ROOT = ""
    private val OFFLINE_FLAG = 999

    private lateinit var obj: AFile

    override var currentPath = ""

    private var loadDialog: ProgressDialog? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        if (!CheckConnection.isOnline(this@DropboxManAct)) {
            startActivityForResult(Intent(this@DropboxManAct, ReconnectActivity::class.java), OFFLINE_FLAG)
        }

        obj = (application as ThisApplication).fileApiFactory(this)
        setContentView(R.layout.file_man_view)
        view = findViewById(R.id.file_man_list) as ListView

        val checkList: ShortArray?
        if (savedInstanceState == null) {
            initializeView()
        } else {
            restoreView(savedInstanceState)
        }
        checkList = setCheckList(savedInstanceState)

        setAdapter(
                if (!isChecking)
                    ViewLayout.LIST_BASIC
                else
                    ViewLayout.LIST_CHECK, checkList
        )

        view?.onItemClickListener = this

        btnFun()

    }

    private fun btnFun() {
        select_all_btn.onClick {
            val tempArray = modAdapter.getIsSelected()
            for (i in 0..tempArray.size() - 1) {
                modAdapter.notIsSelected(i)
            }
            runOnUiThread { modAdapter.notifyDataSetChanged() }
        }

        confirmBtn_fileman.onClick {
            //TODO
            toast("OK")
        }

        cancelBtn_fileman.onClick {
            finish()
        }
    }

    private fun  setCheckList(savedInstanceState: Bundle?): ShortArray? {
        return savedInstanceState?.getShortArray("checkList")
    }

    private fun restoreView(savedInstanceState: Bundle) {
        currentPath = savedInstanceState.getCharSequence("currentPath").toString()
        freeThread(Runnable { updateBundle(currentPath) })
        isChecking = savedInstanceState.getCharSequence("listStatus") == true.toString()
    }

    /**
     * IO
     */
    private fun initializeView() {
        tree.setRoot(tree.rootNodeFactory(ROOT))
        freeThread(Runnable { updateBundle(ROOT) })
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (resultCode == RESULT_OK && requestCode == OFFLINE_FLAG) {
            restartActivity()
        }
    }

    override fun onSaveInstanceState(outState: Bundle?) {
        outState?.putCharSequence("currentPath", currentPath)
        outState?.putCharSequence("listStatus", isChecking.toString())
        val temp = ShortArray(modAdapter.getIsSelected().size())
        for (i in 0..temp.size - 1)
            temp[i] = if (modAdapter.getIsSelected()[i]) 1 else 0
        outState?.putShortArray("checkList", temp)
        super.onSaveInstanceState(outState)
    }

    override fun changeDir(position: Int) {
        val path: String

        if (!showList[position].equals("../") && !showList[position].equals("/")) {
            path = tree.get((showList[position]).split("/")[0])?.path as String
        } else {
            path = when (showList[position]) {
                "../" -> tree.get(currentPath)?.parentPath as String
                "/" -> ROOT
                else -> throw Exception("Check$this")
            }
        }

        loadDialog = ProgressDialog.show(this@DropboxManAct, "", "Loading...")
        if (path != ROOT) {
                var metadata: Metadata?
                freeThread(Runnable {
                    metadata = obj.getMetadata(path)

                    if (metadata is FolderMetadata) {
                        LogInstance.log("Renew List", path, LogInstance.LogType.DEBUG, showLog)
                        renewList(path)
                    } else {
                        threadExecCb(Runnable { obj.downloadFile(metadata as FileMetadata) })
                    }
                })
        } else {
            renewList(ROOT)
        }
    }

    override fun renewList(path: String) {
        freeThread(Runnable { updateBundle(path) })
        currentPath = path
    }

    /**
     * Get the directory list from dropbox
     */
    override fun updateBundle(path: String) {
        val targetList = tree.searchList(path) as TreeList
        LogInstance.log("treelist isInitialized", targetList.isInitialized.toString(), LogInstance.LogType.DEBUG, showLog)

        if (!targetList.isInitialized) {
            val result = obj.getFolderList(tree, path)

            if (result !== null) {
                collectionAmend(path)
            } else {
                toast("Error! Try again later!")
                finish()
            }
        } else {
            collectionAmend(path)
        }

        runOnUiThread {
            modAdapter.notifyDataSetChanged()
            loadDialog?.dismiss()
        }
    }

    private fun collectionAmend (path: String) {
        tree.putAll(obj.toArrayList(path, tree), obj.toMap(path, tree), path)
        showList.clear()
        showList.addAll(obj.toArrayList(path, tree))
    }

    private fun freeThread(runnable: Runnable) {
        (application as ThisApplication).runOnBg(runnable)
    }

    private fun threadExec(runnable: Runnable) {
        (application as ThisApplication).runOnBgAndJoin(runnable)
    }

    private fun threadExecCb(runnable: Runnable) {
        (application as ThisApplication).runOnBgWithCb(runnable, this)
    }

    override fun threadFinish() {
        LogInstance.log("$this CB", "CB invoked", LogInstance.LogType.DEBUG, showLog)
        toast("Complete!")
    }

}
